package thread;
//TODO 单例模式之懒汉模式
class SingletonLazy{
    //这个引用指定唯一实例,这个引用先初始化为Null,而不是直接创建实例
    private volatile static SingletonLazy instance = null;//这里加volatile就是阻止指令重排序
    private static Object locker = new Object();
    public static SingletonLazy getInstance() {
        if (instance == null) {//是否要加锁
            //如果instance是null,就说明是首次调用,首次调用就要考虑线程安全问题就要加锁
            //如果非null就说明是后续的调用,就不必加锁了
            synchronized (locker) {
                if (instance == null) {//是否要创建对象
                    instance = new SingletonLazy();//写操作,懒汉模式线程不安全,多个线程调度顺序,可能会创建出多个实例
                }
            }//但是这样效率很低,因为只要instance非null就不会有线程安全问题了,但是后续任然要每次加一次锁,就浪费了,所以再套一层if
        }
        return instance;
        //这就是双重校验锁
    }
    //如果是首次调用getInstance,那么此时Instance引用为null
    //就会进去到If里面创建实例
    //如果是后续再次调用getInstance,由于instance已经不是null
    //此时就不会进入if,直接返回之前创建好的引用
    //这样 设定,也可以保证该实例是唯一一个
    //同时,创建实例的时机就不是程序驱动时,而是第一次调用getInstance的时候
    //比起饿汉就晚了很多,如果不调用,那么就可以剩下创建实例这个操作
        private  SingletonLazy(){
        }
}
public class ThreadDemo27 {
    public static void main(String[] args) {
    SingletonLazy s1 = SingletonLazy.getInstance();
    SingletonLazy s2 = SingletonLazy.getInstance();
        System.out.println(s1 == s2);
    }
}
